home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1994 #2
/
Monster Media No. 2 (Monster Media)(1994).ISO
/
utils2
/
pgpsort.zip
/
PGPSORT.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1994-05-27
|
13KB
|
401 lines
program PGPSort;
{ }
{ PGPSORT v1.02 by Ståle Schumacher/Felix Softworks 1994 }
{ }
{ Syntax : PGPSORT [-KeyID|-UserID|-Size|-Date] [<keyring>] }
{ }
{ Synopsis: Sorts PGP public key rings. }
{ }
{ History : v1.02 - Now sorts keyIDs according to last 32 bits (was 24) }
{ v1.01 - Improved sorting of 'unstandard' user IDs }
{ v1.00 - Original version }
{ }
{ Examples: PGPSORT - Sorts your main public key ring }
{ (PUBRING.PGP) according to the }
{ user IDs on the keys }
{ PGPSORT -Date PUBRING2.PGP - Sorts the key ring PUBRING2.PGP }
{ according to the date of creation }
{ of the keys }
{ }
{ The files PGPSORT.PAS and PGPSORT.EXE are placed in the public domain and }
{ may be freely distributed and modified. Any questions should be addressed }
{ to the author at: }
{ }
{ Internet : staalesc@ifi.uio.no }
{ }
{ SoundServer BBS: +47 22 57 16 00 }
{ Ståle Schumacher }
{ }
{ Snail mail : Ståle Schumacher }
{ Gyldenlovesgate 24 }
{ N-0260 Oslo }
{ NORWAY }
{ }
{$A+,B-}
{$M 32768,0,655360}
uses
Dos;
const
Version = '1.02';
RevisionDate = '1994/05/27';
MaxKeys = 10000;
type
KeyPtr = ^KeyRec;
KeyRec = record
fPos,
length : longint;
keyID : longint;
userID : string[25];
size : integer;
date : longint;
end;
var
SortCriterion: (KeyID,UserID,Size,Date);
keys : integer;
key : array[0..MaxKeys] of KeyPtr;
procedure Error(const msg: string);
begin
WriteLn(msg);
Halt(1);
end;
function FileExists(const fileName: PathStr): boolean;
var
DirInfo: SearchRec;
begin
FindFirst(fileName,Archive,DirInfo);
FileExists:=(DosError=0) and (fileName<>'');
end;
function NoDirInName(const fileName: PathStr): boolean;
var
i: Integer;
begin
NoDirInName:=True;
for i:=1 to Length(fileName) do
if fileName[i] in [':','\'] then
NoDirInName:=False;
end;
function DirWithSlash(const dir: DirStr): DirStr;
begin
if (dir<>'') and (Copy(dir,Length(dir),1)<>'\') then
DirWithSlash:=dir+'\'
else
DirWithSlash:=dir;
end;
function UpperCase(s: string): string; near; assembler;
asm
PUSH DS
LDS SI,[BP+4]
LES DI,[BP+8]
CLD
LODSB
STOSB
XOR CH,CH
MOV CL,AL
JCXZ @3
@1:
LODSB
CMP AL,'a'
JB @2
CMP AL,'z'
JA @2
SUB AL,'a'-'A'
@2:
STOSB
LOOP @1
@3:
POP DS
end;
procedure QuickSort;
function Sorted(a,b: integer): boolean;
begin
case SortCriterion of
KeyID : if (key[a]^.keyID < 0) and (key[b]^.keyID > 0) then
Sorted:=false
else if (key[a]^.keyID > 0) and (key[b]^.keyID < 0) then
Sorted:=true
else
Sorted := key[a]^.keyID < key[b]^.keyID;
UserID: Sorted := key[a]^.userID < key[b]^.userID;
Size : Sorted := key[a]^.size < key[b]^.size;
Date : Sorted := key[a]^.date < key[b]^.date;
end;
end;
procedure SwapKeys(a,b: integer);
var
x: KeyPtr;
begin
x:=key[a];
key[a]:=key[b];
key[b]:=x;
end;
procedure Sort(left,right: integer);
var
i,j: integer;
begin
i:=left; j:=right;
key[0]^:=key[(left+right) div 2]^;
repeat
while Sorted(i,0) do
inc(i);
while Sorted(0,j) do
dec(j);
if i<=j then
begin
SwapKeys(i,j);
inc(i); dec(j);
end;
until i>j;
if left<j then
Sort(left,j);
if i<right then
Sort(i,right);
end;
begin
Sort(1,keys);
end;
procedure SortKeyRing(const keyRing: PathStr);
const
LengthArray: array[0..3] of byte = (1,2,4,0);
var
f,newF : file;
i,j,b,
CTB,
LengthOfLength : byte;
PacketLength,
timeStamp,fPos : longint;
bits : word;
KeyID : longInt;
UserID : string;
junk : string[2];
firstUserID : boolean;
dir : DirStr;
name : NameStr;
ext : ExtStr;
buf : array[1..2048] of byte;
bakName : string;
bytes : integer;
begin
keys:=0;
fPos:=0;
GetMem(key[0],SizeOf(KeyRec));
Assign(f,KeyRing); Reset(f,1);
while fPos<FileSize(f) do
begin
Seek(f,fPos);
BlockRead(f,CTB,1);
LengthOfLength:=CTB and 3;
LengthOfLength:=LengthArray[LengthOfLength];
CTB:=CTB and 60;
if CTB=24 then {Public key packet}
begin
inc(keys);
if keys>MaxKeys then
Error('The keyring '+keyRing+' is too long to sort.');
GetMem(key[keys],SizeOf(KeyRec));
if key[keys]=nil then
Error('The keyring '+keyRing+' is too long to sort.');
key[keys]^.fPos:=fpos;
key[keys-1]^.length:=fpos-key[keys-1]^.fPos;
firstUserID:=true;
PacketLength:=0;
for i:=1 to LengthOfLength do
begin
BlockRead(f,b,1);
PacketLength:=(PacketLength shl 8)+b;
end;
BlockRead(f,junk,1);
BlockRead(f,b,1); TimeStamp:=b;
BlockRead(f,b,1); TimeStamp:=(TimeStamp shl 8) or b;
BlockRead(f,b,1); TimeStamp:=(TimeStamp shl 8) or b;
BlockRead(f,b,1); TimeStamp:=(TimeStamp shl 8) or b;
BlockRead(f,junk,3);
BlockRead(f,Bits,2); bits:=Swap(bits);
Seek(f,FilePos(f)+((bits+7) div 8)-4);
BlockRead(f,b,1); keyID:=b;
BlockRead(f,b,1); keyID:=(keyID shl 8) or b;
BlockRead(f,b,1); keyID:=(keyID shl 8) or b;
BlockRead(f,b,1); keyID:=(keyID shl 8) or b;
key[keys]^.size :=bits;
key[keys]^.keyID:=keyID;
key[keys]^.date :=TimeStamp;
fPos:=fPos+LengthOfLength+PacketLength+1;
end
else if CTB=52 then {User ID packet}
begin
PacketLength:=0;
BlockRead(f,PacketLength,1);
Seek(f,FilePos(f)-1);
BlockRead(f,UserID,PacketLength+1);
UserID:=UpperCase(UserID);
if firstUserID then
begin
firstUserID:=false;
b:=1;
while (b<=Length(UserID)) and
not (((UserID[b] in ['0'..'9']) and (UserID[b-1]<>'-'))
or (UserID[b] in ['[','<','(','+'])
or (Copy(UserID,b,2)='- ')) do
inc(b);
UserID[0]:=CHAR(b-1);
while Copy(UserID,Length(UserID),1)=' ' do dec(UserID[0]);
{Derive name from internet address?}
if (Pos(' ',UserID)=0) and (Pos('@',UserID)>0) then
begin
UserID[0]:=char(Pos('@',UserID)-1);
b:=Pos('.',UserID);
if b>0 then UserID[b]:=' ';
end;
{Split first and last names}
if Pos(' ',UserID)=0 then
key[keys]^.userID:=UserID
else
begin
b:=Pos(', ',UserID);
if (b>0) and (b+1=Pos(' ',UserID)) then
key[keys]^.userID:=UserID
else
begin
b:=Length(UserID);
while (UserID[b]<>' ') do dec(b);
key[keys]^.userID:=Copy(UserID,b+1,Length(UserID))+', '+Copy(UserID,1,b-1);
end;
end;
end;
fPos:=fPos+PacketLength+2;
end
else if CTB=48 then {Keyring trust packet}
fPos:=fPos+3
else if CTB=8 then {Signature packet}
begin
PacketLength:=0;
for i:=1 to LengthOfLength do
begin
BlockRead(f,b,1);
PacketLength:=(PacketLength SHL 8)+b;
end;
fPos:=fPos+LengthOfLength+PacketLength+1;
end
else {Unknown packet}
Error(keyRing+' is not a public key ring.');
end;
key[keys]^.length:=FileSize(f)-key[keys]^.fPos;
Close(f);
if keys=0 then
Error(keyRing+' is not a public key ring.');
{Sort keys}
QuickSort;
{Backup old keyring}
FSplit(KeyRing,Dir,Name,Ext);
bakName:=Dir+Name+'.BAK';
Assign(f,bakName); {$I-} Erase(f); {$I+}
if IOResult<>0 then {Old backup not found};
Assign(f,KeyRing); Rename(f,bakName);
{Generate new keyring}
Assign(f,bakName); Reset(f,1);
Assign(newF,KeyRing); Rewrite(newF,1);
for i:=1 to keys do
begin
Seek(f,key[i]^.fPos);
while key[i]^.length>0 do
begin
bytes:=key[i]^.length; if bytes>SizeOf(buf) then bytes:=SizeOf(buf);
BlockRead(f,buf,bytes);
BlockWrite(newF,buf,bytes);
dec(key[i]^.length,bytes);
end;
end;
Close(f); Close(newF);
for i:=0 to keys do
FreeMem(key[i],SizeOf(KeyRec));
end;
procedure WriteSyntax;
begin
WriteLn('Syntax: PGPSORT [-KeyID|-UserID|-Size|-Date] [<keyring>]');
Halt(1);
end;
var
i : integer;
mode,
KeyRing: string;
begin
WriteLn;
WriteLn('PGPSORT v',Version,' (C) 1994 Felix Softworks');
WriteLn('Written by Ståle Schumacher ',RevisionDate);
WriteLn;
KeyRing:='PUBRING.PGP';
SortCriterion:=UserID;
if ParamCount in [1,2] then
begin
mode:=UpperCase(ParamStr(1));
if mode='-KEYID' then
SortCriterion:=KeyID
else if mode='-USERID' then
SortCriterion:=UserID
else if mode='-SIZE' then
SortCriterion:=Size
else if mode='-DATE' then
SortCriterion:=Date
else if Copy(mode,1,1)='-' then
WriteSyntax
else if ParamCount=2 then
WriteSyntax
else
KeyRing:=UpperCase(ParamStr(1));
if ParamCount=2 then
begin
KeyRing:=UpperCase(ParamStr(2));
if Copy(KeyRing,1,1)='-' then
WriteSyntax;
end
end
else if ParamCount<>0 then
WriteSyntax;
if not FileExists(KeyRing) then
begin
if NoDirInName(KeyRing) then
KeyRing:=DirWithSlash(UpperCase(GetEnv('PGPPATH')))+KeyRing;
if not FileExists(KeyRing) then
Error(KeyRing+' not found.');
end;
SortKeyRing(KeyRing);
Write(KeyRing,' sorted on ');
case SortCriterion of
KeyID : WriteLn('key ID.');
UserID: WriteLn('user ID.');
Size : WriteLn('size.');
Date : WriteLn('date.');
end;
end.